#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
简化版预测模型 - 专注于中长期趋势预测
不依赖复杂的机器学习库，使用技术分析和统计方法
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import warnings
warnings.filterwarnings('ignore')

class SimplePredictionModel:
    """简化版预测模型"""
    
    def __init__(self):
        self.min_data_points = 30
        
    def predict_price(self, data, stock_code):
        """预测股票价格趋势"""
        if data.empty or len(data) < self.min_data_points:
            return {
                'trend': '数据不足',
                'confidence': 0,
                'reason': '历史数据不足，无法进行预测'
            }
        
        try:
            # 基础数据准备
            close_prices = data['close'].values
            volumes = data['volume'].values
            
            # 1. 趋势分析
            trend_score = self._analyze_trend(close_prices)
            
            # 2. 动量分析
            momentum_score = self._analyze_momentum(close_prices, volumes)
            
            # 3. 均值回归分析
            mean_reversion_score = self._analyze_mean_reversion(close_prices)
            
            # 4. 成交量分析
            volume_score = self._analyze_volume(volumes, close_prices)
            
            # 综合评分
            total_score = (
                trend_score * 0.4 +
                momentum_score * 0.3 +
                mean_reversion_score * 0.2 +
                volume_score * 0.1
            )
            
            # 确定趋势方向
            if total_score > 15:
                trend = '上涨'
                confidence = min(0.8, (total_score - 15) / 25 + 0.3)
            elif total_score < -15:
                trend = '下跌'
                confidence = min(0.8, abs(total_score + 15) / 25 + 0.3)
            else:
                trend = '震荡'
                confidence = 0.5 - abs(total_score) / 30
            
            # 预测未来价格
            current_price = close_prices[-1]
            if trend == '上涨':
                expected_change = confidence * 0.1  # 最多10%涨幅预期
            elif trend == '下跌':
                expected_change = -confidence * 0.08  # 最多8%跌幅预期
            else:
                expected_change = 0
            
            next_day_price = current_price * (1 + expected_change)
            
            return {
                'trend': trend,
                'confidence': confidence,
                'next_day_price': next_day_price,
                'current_price': current_price,
                'expected_change_pct': expected_change * 100,
                'trend_score': trend_score,
                'momentum_score': momentum_score,
                'mean_reversion_score': mean_reversion_score,
                'volume_score': volume_score,
                'total_score': total_score
            }
            
        except Exception as e:
            return {
                'trend': '预测失败',
                'confidence': 0,
                'reason': f'预测过程出现错误: {e}'
            }
    
    def _analyze_trend(self, prices):
        """分析价格趋势"""
        if len(prices) < 20:
            return 0
            
        # 计算多周期移动平均线
        ma5 = pd.Series(prices).rolling(5).mean().iloc[-1]
        ma10 = pd.Series(prices).rolling(10).mean().iloc[-1]
        ma20 = pd.Series(prices).rolling(20).mean().iloc[-1]
        
        current_price = prices[-1]
        score = 0
        
        # 均线排列
        if current_price > ma5 > ma10 > ma20:
            score += 25  # 完美多头排列
        elif current_price > ma5 > ma10:
            score += 15  # 短期多头
        elif current_price > ma5:
            score += 8   # 极短期多头
        elif current_price < ma5 < ma10 < ma20:
            score -= 25  # 完美空头排列
        elif current_price < ma5 < ma10:
            score -= 15  # 短期空头
        elif current_price < ma5:
            score -= 8   # 极短期空头
        
        # 价格相对于均线的位置
        if len(prices) >= 20:
            ma20_slope = (ma20 - pd.Series(prices).rolling(20).mean().iloc[-10]) / ma20
            if ma20_slope > 0.02:  # 均线向上
                score += 10
            elif ma20_slope < -0.02:  # 均线向下
                score -= 10
        
        return score
    
    def _analyze_momentum(self, prices, volumes):
        """分析价格动量"""
        if len(prices) < 10:
            return 0
            
        score = 0
        
        # 短期动量（5日）
        short_momentum = (prices[-1] - prices[-6]) / prices[-6] if len(prices) > 5 else 0
        if short_momentum > 0.05:  # 5日涨幅超过5%
            score += 15
        elif short_momentum > 0.02:  # 5日涨幅超过2%
            score += 8
        elif short_momentum < -0.05:  # 5日跌幅超过5%
            score -= 15
        elif short_momentum < -0.02:  # 5日跌幅超过2%
            score -= 8
        
        # 中期动量（20日）
        if len(prices) >= 20:
            medium_momentum = (prices[-1] - prices[-21]) / prices[-21]
            if medium_momentum > 0.15:  # 20日涨幅超过15%
                score += 20
            elif medium_momentum > 0.08:  # 20日涨幅超过8%
                score += 12
            elif medium_momentum < -0.15:  # 20日跌幅超过15%
                score -= 20
            elif medium_momentum < -0.08:  # 20日跌幅超过8%
                score -= 12
        
        # 价格加速度
        if len(prices) >= 15:
            recent_slope = np.polyfit(range(5), prices[-5:], 1)[0]
            earlier_slope = np.polyfit(range(5), prices[-15:-10], 1)[0]
            acceleration = recent_slope - earlier_slope
            
            if acceleration > 0:
                score += 8
            elif acceleration < 0:
                score -= 8
        
        return score
    
    def _analyze_mean_reversion(self, prices):
        """分析均值回归"""
        if len(prices) < 20:
            return 0
            
        # 计算价格相对于历史均值的位置
        mean_price = np.mean(prices[-60:]) if len(prices) >= 60 else np.mean(prices)
        std_price = np.std(prices[-60:]) if len(prices) >= 60 else np.std(prices)
        
        current_price = prices[-1]
        z_score = (current_price - mean_price) / std_price if std_price > 0 else 0
        
        score = 0
        
        # 基于Z-score的均值回归信号
        if z_score > 2:  # 价格严重偏高
            score -= 15
        elif z_score > 1:  # 价格偏高
            score -= 8
        elif z_score < -2:  # 价格严重偏低
            score += 15
        elif z_score < -1:  # 价格偏低
            score += 8
        
        # 布林带位置
        if len(prices) >= 20:
            ma20 = pd.Series(prices).rolling(20).mean().iloc[-1]
            std20 = pd.Series(prices).rolling(20).std().iloc[-1]
            upper_band = ma20 + 2 * std20
            lower_band = ma20 - 2 * std20
            
            if current_price > upper_band:  # 突破上轨
                score -= 10
            elif current_price < lower_band:  # 跌破下轨
                score += 10
        
        return score
    
    def _analyze_volume(self, volumes, prices):
        """分析成交量"""
        if len(volumes) < 10:
            return 0
            
        score = 0
        
        # 成交量变化
        recent_volume = np.mean(volumes[-5:])
        historical_volume = np.mean(volumes[:-5]) if len(volumes) > 5 else recent_volume
        
        volume_ratio = recent_volume / historical_volume if historical_volume > 0 else 1
        
        # 量价配合分析
        price_change = (prices[-1] - prices[-6]) / prices[-6] if len(prices) > 5 else 0
        
        if price_change > 0 and volume_ratio > 1.5:  # 价涨量增
            score += 12
        elif price_change > 0 and volume_ratio < 0.8:  # 价涨量缩
            score -= 5
        elif price_change < 0 and volume_ratio > 1.5:  # 价跌量增
            score -= 12
        elif price_change < 0 and volume_ratio < 0.8:  # 价跌量缩
            score += 5
        
        # 异常成交量
        if volume_ratio > 3:  # 成交量异常放大
            score += 8
        elif volume_ratio < 0.3:  # 成交量异常萎缩
            score -= 5
        
        return score
    
    def get_risk_assessment(self, data):
        """获取风险评估"""
        if data.empty or len(data) < 20:
            return {
                'risk_level': '无法评估',
                'volatility': 0,
                'max_drawdown': 0
            }
        
        # 计算波动率
        returns = data['close'].pct_change().dropna()
        volatility = returns.std() * np.sqrt(252) * 100  # 年化波动率
        
        # 计算最大回撤
        rolling_max = data['close'].expanding().max()
        drawdown = (data['close'] - rolling_max) / rolling_max
        max_drawdown = drawdown.min() * 100
        
        # 风险等级
        if volatility < 20 and max_drawdown > -15:
            risk_level = '低风险'
        elif volatility < 35 and max_drawdown > -25:
            risk_level = '中等风险'
        else:
            risk_level = '高风险'
        
        return {
            'risk_level': risk_level,
            'volatility': volatility,
            'max_drawdown': max_drawdown
        }

# 为了兼容性，创建别名
PredictionModel = SimplePredictionModel
